import data from "../../core/cache_data";
import { LibraryRecord } from "../../core/library";
import { Serialize, SerializeClass, StrDataReader, StrDataWriter } from "../../core/serialize";
import { BulletGameUtils } from "./assets/game/bullet_game_utils";
import Bullet from "./bullet";
import { EditorAttr, EditorAttrConfig, EditorAttrItem, GetEditorAttrListByTarget } from "./bullet_editor_attribute";
import World from "./world";

@SerializeClass("WorldData")
export class WorldData extends LibraryRecord {
    @EditorAttr("KEY")
    @Serialize()
    override key = "";
    @EditorAttr("中文名")
    @Serialize()
    name = "";
    @EditorAttr("描述")
    @Serialize()
    desc = "";
    @EditorAttr("重生点X")
    @Serialize()
    bornPointX = 0;
    @EditorAttr("重生点Y")
    @Serialize()
    bornPointY = 0;
    @Serialize()
    data = ""; //编辑器数据 
};


export class WorldDataReadWrite {
    static SaveWorldData(world: World, bullets: Bullet[]) {
        let w = new StrDataWriter();
        //数据版本(与软件版本绑定)
        w.writeDynamicString(data.gameConfig.version);

        //地图尺寸
        w.writeDynamicInt(Math.floor(world.node.width / 100));
        w.writeDynamicInt(Math.floor(world.node.height / 100));

        //重力
        w.writeDynamicSignInt(Math.floor(world.gravity.x / 100));
        w.writeDynamicSignInt(Math.floor(world.gravity.y / 100));

        //bullet列表
        w.writeDynamicInt(bullets.length);
        bullets.forEach(bullet => {
            //基础属性
            w.writeDynamicString(bullet.node.name);
            w.writeDynamicString(bullet.tag);
            w.writeDynamicSignInt(bullet.node.x);
            w.writeDynamicSignInt(bullet.node.y);
            w.writeDynamicSignInt(bullet.node.width);
            w.writeDynamicSignInt(bullet.node.height);

            let eacWriter = new StrDataWriter();

            let eac: EditorAttrConfig = GetEditorAttrListByTarget(bullet);
            if (eac) {
                eac.items.forEach(item => {
                    // w.writeDynamicString(item.property);
                    this.__writeOneAttr(eacWriter, item, bullet);
                })
            }

            let eacStrLength = `${eacWriter.str.length}`.length;
            w.writeInt(eacStrLength, 1);
            w.writeDynamicString(eacWriter.str, eacStrLength);
        });


        //其他数据
        // let worldOtherData: any = {};
        // world.getComponents(cc.Component).forEach(com => {
        //     let eac = GetEditorAttrListByCtor(com.constructor);
        //     if (eac) {
        //         let comName = cc.js.getClassName(com.constructor);
        //         worldOtherData[comName] = {};
        //         eac.items.forEach(item => {
        //             let key = item.property;
        //             worldOtherData[comName][key] = com[key];
        //         });
        //     }
        // });
        // let comList = Object.keys(worldOtherData);
        // w.writeDynamicInt(comList.length);
        // for (let i = 0; i < comList.length; i++) {
        //     w.writeDynamicString(comList[i]); //写类名
        //     let dat = worldOtherData[comList[i]];
        //     let datKeys = Object.keys(dat);
        //     w.writeDynamicInt(datKeys.length); //写属性数量
        //     datKeys.forEach(key => {
        //         this.__writeOneAttr(w, key, dat);
        //     });
        // }

        // //动态BULLET spawn  数据
        // let spawns = world.getComponentsInChildren(BulletSpawner);
        // w.writeDynamicInt(spawns.length);
        // spawns.forEach(spawn => {
        //     w.writeDynamicString(spawn.node.name);
        //     w.writeDynamicString(spawn.tag);
        //     w.writeDynamicSignInt(Math.floor(spawn.node.x / 100));
        //     w.writeDynamicSignInt(Math.floor(spawn.node.y / 100));
        // });
        return w.str;
    }

    static ReadDataToWorld(world: World, editorData: string) {
        if (!editorData) {
            return [];
        }
        let r = new StrDataReader(editorData);
        //数据版本
        let version = r.readDynamicString();
        return this.__readDataToWorld(world, r);
    }

    private static __readDataToWorld(world: World, r: StrDataReader) {
        //尺寸
        world.node.width = r.readDynamicInt() * 100;
        world.node.height = r.readDynamicInt() * 100;
        //重力
        world.gravity.x = r.readDynamicSignInt() * 100;
        world.gravity.y = r.readDynamicSignInt() * 100;

        //bullets
        let bulletsFromEditor = this.__readBullets(world, r);

        //其他数据
        // let comCount = r.readDynamicInt();
        // for (let i = 0; i < comCount; i++) {
        //     let comName = r.readDynamicString(); //读类名
        //     let com = world.getComponent(comName);
        //     let attrCount = r.readDynamicInt(); //读属性数量
        //     for (let c = 0; c < attrCount; c++) {
        //         this.__readOneAttr(r, com);
        //     }
        // }

        // //动态BULLET数据
        // let spawnCount = r.readDynamicInt();
        // for (let i = 0; i < spawnCount; i++) {
        //     let node = new cc.Node(r.readDynamicString());
        //     let spawn = node.addComponent(BulletSpawner);
        //     spawn.tag = r.readDynamicString();
        //     spawn.node.x = r.readDynamicSignInt() * 100;
        //     spawn.node.y = r.readDynamicSignInt() * 100;
        //     world.node.addChild(node);
        // }

        return bulletsFromEditor;
    }

    private static __readBullets(world: World, r: StrDataReader) {
        let bulletsFromEditor: Bullet[] = [];
        let bulletCount = r.readDynamicInt();
        for (let i = 0; i < bulletCount; i++) {
            //基础属性
            let prefabName = r.readDynamicString();
            let bullet = BulletGameUtils.InstantiateBullet(prefabName, Bullet);
            bullet.tag = r.readDynamicString();
            let pos = cc.v2(
                r.readDynamicSignInt(),
                r.readDynamicSignInt(),
            );
            bullet.node.width = r.readDynamicSignInt();
            bullet.node.height = r.readDynamicSignInt();

            let eacData = r.readDynamicString(r.readInt(1));
            let eacReader = new StrDataReader(eacData);

            let eac: EditorAttrConfig = GetEditorAttrListByTarget(bullet);
            if (eac) {
                eac.items.forEach(item => {
                    this.__readOneAttr(eacReader, item, bullet);
                });
            }
            bullet.enterWorld(world);
            bulletsFromEditor.push(bullet);
            bullet.curPos = pos;
            bullet.isCreateFromEditor = true;
        }

        return bulletsFromEditor;

    }
    private static __readOneAttr(r: StrDataReader, item: EditorAttrItem, obj: any) {//key: string, r: StrDataReader, obj: any) {
        let oriVal = obj[item.property];
        switch (item.type) {
            case "color":
                obj[item.property] = r.read(8);
                break;
            case "vec2":
                obj[item.property].x = r.readDynamicInt()
                obj[item.property].y = r.readDynamicInt()
                break;
            case "boolean":
                obj[item.property] = r.readBool();
                break;
            case "number":
                obj[item.property] = r.readDynamicInt();
                break;
            case "string":
                obj[item.property] = r.readDynamicString();
                break;
            default:
                break;
        }
    }
    private static __writeOneAttr(w: StrDataWriter, item: EditorAttrItem, obj: any) {
        let val = obj[item.property];

        switch (item.type) {
            case "color":
                w.write(val); // "#rrggbbaa" 9
                break;
            case "vec2":
                //todo:注意大数据
                w.writeDynamicSignInt(~~val.x);
                w.writeDynamicSignInt(~~val.y);
                break;
            case "boolean":
                w.writeBool(val);
                break;
            case "number":
                w.writeDynamicInt(val);
                break;
            case "string":
                w.writeDynamicString(val);
                break;
            default:
                break;
        }
    }
};